Linux webm002.cluster126.gra.hosting.ovh.net 6.18.39-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Tue Jul 21 12:03:15 CEST 2026 x86_64
/
home
/
ariannadhf
/
www
/
wp-content
/
plugins
/
simple-history
/
inc
/
channels
/
/home/ariannadhf/www/wp-content/plugins/simple-history/inc/channels/class-channels-manager.php
<?php namespace Simple_History\Channels; use Simple_History\Services\Service; /** * Manages all log forwarding channels. * * This service coordinates the registration and processing of channels * that forward Simple History events to external systems. * * @since 4.4.0 */ class Channels_Manager extends Service { /** * Array of registered channels. * * @var Channel_Interface[] */ private array $channels = []; /** * Called when service is loaded. */ public function loaded() { // Register core channels. $this->register_core_channels(); // Hook for premium channels to register themselves. do_action( 'simple_history/channels/register', $this ); // Hook into the logging system to process events. add_action( 'simple_history/log/inserted', [ $this, 'process_logged_event' ], 10, 3 ); } /** * Register core channels that come with the free plugin. */ private function register_core_channels() { // Some users report "Class File_Channel not found" errors during plugin updates. // We haven't been able to reproduce this, but checking class_exists() first // should prevent the fatal error for those affected. if ( ! class_exists( File_Channel::class ) ) { return; } $this->register_channel( new File_Channel() ); } /** * Register an channel. * * @param Channel_Interface $channel The channel to register. * @return bool True on success, false if already registered. */ public function register_channel( Channel_Interface $channel ) { $slug = $channel->get_slug(); if ( isset( $this->channels[ $slug ] ) ) { return false; // Already registered. } $this->channels[ $slug ] = $channel; // Call loaded() to allow channel to register hooks. // This is separate from construction to keep instantiation side-effect free. $channel->loaded(); /** * Fired when an channel is registered. * * @param Channel_Interface $channel The registered channel. * @param Channels_Manager $manager This manager instance. */ do_action( 'simple_history/channels/registered', $channel, $this ); return true; } /** * Get a registered channel by slug. * * @param string $slug The channel slug. * @return Channel_Interface|null The channel or null if not found. */ public function get_channel( $slug ) { return $this->channels[ $slug ] ?? null; } /** * Get all registered channels. * * @return Channel_Interface[] Array of channels. */ public function get_channels() { return $this->channels; } /** * Get all enabled channels. * * @return Channel_Interface[] Array of enabled channels. */ public function get_enabled_channels() { return array_filter( $this->channels, function ( $channel ) { return $channel->is_enabled(); } ); } /** * Process a logged event and send to enabled channels. * * @param array $context Context data for the event. * @param array $data Event data. * @param mixed $logger Logger instance that created the event. */ public function process_logged_event( $context, $data, $logger ) { $enabled_channels = $this->get_enabled_channels(); if ( empty( $enabled_channels ) ) { return; } // Prepare event data for channels. $event_data = $this->prepare_event_data( $context, $data, $logger ); foreach ( $enabled_channels as $channel ) { $this->send_to_channel( $channel, $event_data ); } } /** * Prepare event data for sending to channels. * * @param array $context Context data for the event. * @param array $data Event data. * @param mixed $logger Logger instance that created the event. * @return array Prepared event data. */ private function prepare_event_data( $context, $data, $logger ) { return [ 'id' => $data['id'] ?? null, 'date' => $data['date'] ?? current_time( 'mysql' ), 'logger' => $data['logger'] ?? '', 'level' => $data['level'] ?? 'info', 'message' => $data['message'] ?? '', 'initiator' => $data['initiator'] ?? '', 'context' => $context, 'logger_instance' => $logger, ]; } /** * Send event data to a specific channel. * * @param Channel_Interface $channel The channel to send to. * @param array $event_data The event data to send. */ private function send_to_channel( Channel_Interface $channel, $event_data ) { // Check if the event should be sent based on alert rules. if ( ! $channel->should_send_event( $event_data ) ) { return; } // Format the message for the channel. $formatted_message = $this->format_message_for_channel( $channel, $event_data ); // Determine if we should process async or sync. if ( $channel->supports_async() && $this->should_process_async( $channel ) ) { $this->queue_for_async_processing( $channel, $event_data, $formatted_message ); } else { $this->send_sync( $channel, $event_data, $formatted_message ); } } /** * Format a message for a specific channel. * * @param Channel_Interface $channel The channel. * @param array $event_data The event data. * @return string The formatted message. */ private function format_message_for_channel( Channel_Interface $channel, $event_data ) { $message = $event_data['message']; if ( ! empty( $event_data['context'] ) ) { $message = \Simple_History\Helpers::interpolate( $message, $event_data['context'] ); } return $message; } /** * Check if a channel should be processed asynchronously. * * @param Channel_Interface $channel The channel. * @return bool True if should process async. */ private function should_process_async( Channel_Interface $channel ) { // For now, always process async if supported. // This could be configurable in the future. return true; } /** * Queue an event for asynchronous processing. * * @param Channel_Interface $channel The channel. * @param array $event_data The event data. * @param string $formatted_message The formatted message. */ private function queue_for_async_processing( Channel_Interface $channel, $event_data, $formatted_message ) { // TODO: Implement async queue system using WordPress cron. // For now, fall back to synchronous processing. $this->send_sync( $channel, $event_data, $formatted_message ); } /** * Send an event synchronously to an channel. * * @param Channel_Interface $channel The channel. * @param array $event_data The event data. * @param string $formatted_message The formatted message. */ private function send_sync( Channel_Interface $channel, $event_data, $formatted_message ) { // Set filter to indicate we're forwarding to a channel. // This allows other plugins (like Debug & Monitor) to skip logging // HTTP requests made by channels, preventing infinite loops. add_filter( 'simple_history/is_forwarding_to_channel', '__return_true' ); try { $channel->send_event( $event_data, $formatted_message ); } catch ( \Throwable $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch // Catch \Throwable (not just \Exception) to handle \Error too. // During plugin updates, old code in memory may reference classes // that were moved/renamed in the new version on disk, causing // "Class not found" errors (which are \Error, not \Exception). } remove_filter( 'simple_history/is_forwarding_to_channel', '__return_true' ); } }